#pragma once
#include <iostream>
#include <string>
#include <type_traits>
using namespace std;

class student;

class person
{
    friend void display(const person& p, const student& s);
public:
    person(const char* name = "person")
        : _name(name)
    {
        cout << "person(const char* name)" << endl;
        ++_si;
    }

    person(const person& p)
        : _name(p._name)
    {
        cout << "person(const person& p)" << endl;
    }

    person& operator=(const person& p)
    {
        cout << "person operator=(const person& p)" << endl;
        if (this != &p)
            _name = p._name;
        return *this;
    }

    ~person()
    {
        cout << "~person()" << endl;
    }

protected:
    string _name;

public:
    static int _si;
};

int person::_si = 0;

class student : public person
{
    friend void display(const person& p, const student& s);
public:
    student(const char* name = "student", int num = 222)
        : person(name)
        , _num(num)
    {
        cout << "student(const char* name, int num)" << endl;
    }

    student(const student& s)
        : person(s)
        , _num(s._num)
    {
        cout << "student(const student& s)" << endl;
    }

    student& operator=(const student& s)
    {
        cout << "student operator=(const student& s)" << endl;

        if (this != &s)
        {
            person::operator=(s);
            _num = s._num;
        }
        return *this;
    }

    ~student()
    {
        person::~person();
        cout << "~student()" << endl;
    }
protected:
    int _num;
};


void test_4()
{
    student s;
    person p = s;

    student s1(s);
}

void display(const person& p, const student& s)
{
    cout << p._name << endl;
    // cout << s._num << endl; //error
}

void test_5()
{
    person p;
    student s;
    display(p, s);
}

struct A
{
    static int _s_a;
    A() { _s_a++; }
};

int A::_s_a = 0;

struct B : public A
{
    B() { _s_a++; }
};

struct C : public A
{
    C() { _s_a++; }
};

void test_6()
{
    person p;
    student s;

    cout << p._si << endl;
    cout << person::_si << endl;

    A();
    B();
    C();
    cout << A::_s_a << endl;
}
